/*
 * @Descripttion: 日志记录器
 * @Version: 1.0
 * @Author: undead
 * @Date: 2021-03-29 10:41:57
 * @LastEditors: undead
 * @LastEditTime: 2021-12-02 16:29:04
 */
import Browser from "../../model/Browser";
import indexDB from "../lib/dbManage";
import LogInfo from "../../model/LogInfo";
import LogTypeEnum from "../../model/LogTypeEnum";

class Logger {
    private browser: Browser = new Browser();
    private static logger: Logger;
    private constructor() {}
    static create() {
        if (!this.logger) {
            this.logger = new Logger();
        }

        return this.logger;
    }
    private getStackTrace() {
        const trace = { stack: "" };
        try {
            Error.captureStackTrace(trace, this.getStackTrace);
        } catch {
            trace.stack = new Error().stack;
        }

        let lineNumber = 0,
            columnNumber = 0,
            fileURI = "",
            stack = trace.stack.replace("Error", "");

        stack.split(" at ").forEach(x => {
            if (x.toLowerCase().indexOf("zlogs") === -1 && x.indexOf(":") >= 0) {
                const dot = x.split(":");
                lineNumber = parseInt(dot[dot.length - 2]);
                columnNumber = parseInt(dot[dot.length - 1]);
                fileURI = x;
                return false;
            }
            return true;
        });

        return { lineNumber, columnNumber, fileURI, stack };
    }
    private formatData(source: any[]) {
        source.forEach((x, key) => {
            if (typeof x === "object") {
                source[key] = JSON.stringify(x);
            }
        });
    }
    private async addConsole(data: any[], logType: LogTypeEnum) {
        this.formatData(data);

        const { lineNumber, columnNumber, fileURI, stack } = this.getStackTrace();
        const logInfo = new LogInfo();
        logInfo.fileURI = fileURI;
        logInfo.lineNumber = lineNumber;
        logInfo.columnNumber = columnNumber;
        logInfo.type = logType;
        logInfo.message = data.toString();

        switch (logType) {
            case LogTypeEnum.Log:
                logInfo.traceStack = `Log${stack}`;
                break;
            case LogTypeEnum.Info:
                logInfo.traceStack = `Info${stack}`;
                break;
            case LogTypeEnum.Error:
                logInfo.traceStack = `Error${stack}`;
                break;
            case LogTypeEnum.Warn:
                logInfo.traceStack = `Warn${stack}`;
                break;
            default:
                logInfo.traceStack = stack;
                break;
        }
        this.add(logInfo);
    }
    async add(logInfo: LogInfo) {
        return await indexDB.add(logInfo);
    }
    async addConsoleLog(data: any[]) {
        this.addConsole(data, LogTypeEnum.Log);
    }
    async addConsoleInfo(data: any[]) {
        this.addConsole(data, LogTypeEnum.Info);
    }
    async addConsoleError(data: any[]) {
        this.addConsole(data, LogTypeEnum.Error);
    }
    async addConsoleWarn(data: any[]) {
        this.addConsole(data, LogTypeEnum.Warn);
    }
    /**
     * 系统错误信息-添加到日志
     * @param errorMessage 错误信息
     * @param scriptURI 出错文件
     * @param lineNumber 出错行号
     * @param columnNumber 出错列号
     * @param errorObj 错误详情
     */
    async addWindow(errorMessage: string, scriptURI: string, lineNumber: number, columnNumber: number, stack: string) {
        const logInfo = new LogInfo();
        logInfo.fileURI = scriptURI;
        logInfo.lineNumber = lineNumber;
        logInfo.columnNumber = columnNumber;
        logInfo.type = LogTypeEnum.Error;
        logInfo.message = errorMessage;
        logInfo.traceStack = stack;
        this.add(logInfo);
    }
    async getDetailsBySecond(second: number) {
        const localTime = new Date().getTime() - second * 1000;
        const getLogs = await indexDB.getDetails();
        const filterLogs = getLogs.filter(x => x.logCreateTime >= localTime);
        filterLogs.forEach(x => {
            x.logString = JSON.parse(x.logString);
        });
        // console.log(filterLogs);
        return filterLogs.map(x => {
            return x.logString;
        });
    }
}
export default Logger.create();
